#import <UIKit/UIKit.h>
#import "FSServer.h"

extern NSString * const     FSRecordUpdateNotification;		//运动记录更新通知（上传成功或更新后）
extern NSString * const     FSRecordChangeNotification;		//运动记录变化通知（添加、删除记录）

typedef NS_ENUM(int, FSSportType) {
    FSSportTypeFree			= -1,		//自由运动
	
	FSSportTypeIndoor		= 0,		//室内运动	 -
	FSSportTypeTreadmill	= 0,		//跑步机0		(0)
	FSSportTypeElliptical	,			//椭圆机1		(0)
	FSSportTypeBicycle		,			//健身车2		(1)
	
	FSSportTypeOutdoor		= 10,		//户外运动	 -
	FSSportTypeWalking		= 10,		//走路10		(0)
	FSSportTypeRunning		,			//跑步11		(0)
	FSSportTypeCycling		,			//骑车12		(1)
	FSSportTypeRoller		,			//轮滑13		(1)
	FSSportTypeSwimming		,			//游泳14		(0)
	FSSportTypeRowing		,			//划船15		(1)
	FSSportTypeSkiing		,			//滑雪16		(1)
	FSSportTypeClimbing		,			//登山17		(0)
	FSSportTypeRiding		,			//骑马18		(1)
	
	FSSportTypeDriving		= 50,		//驾驶（假数据将列为驾驶）
};

typedef NS_ENUM(int, FSRecordPointType) {
	FSRecordPointTypeNormal		,		//常规记录点
	FSRecordPointTypePause		,		//暂停记录点（在暂停状态下记录的点都为暂停点）
};

typedef NS_ENUM(int, FSRecordState) {
	FSRecordStateNormal			= 0,	//有效记录（此状态的记录参与排名、统计等所有运动成绩）
	FSRecordStateExempt			,		//高质量记录（此状态与有效一样参与所有排名与成绩，同时不接受用户举报及异常处理）
	
	//客户端在进入历史记录详情页面时应提示下述异常状态，同时不允许异常数据用于打卡
	FSRecordStateReport			,		//被举报（举报次数达到一定时，服务器标记为此状态，进入7天申诉期，未申诉并经审核人员确认后删除）
	FSRecordStateInvalid		,		//异常记录（服务器评估为异常或由管理员评估为异常）
	FSRecordStateRepeat			,		//重复记录（与服务器现有记录时间片存在重复）
	FSRecordStateTester			,		//测试员记录（测试员的记录，运动完成后本地应直接设为此状态，并取消上传）
	
	//客户端同步时不会获取到保留期的记录
	FSRecordStateRetention		= 10,	//保留期（用户将正常且5km以上的记录删除后，会在服务器保留30天，在这段时间内用户可申请还原）
};

typedef NS_ENUM(int, FSRecordAction) {
	FSRecordActionPraise		,		//赞
	FSRecordActionComment		,		//评论
	FSRecordActionReport		,		//举报
	FSRecordActionAbnormal		,		//异常（限管理员、圈子管理员(用户本条记录已打卡到圈子时)操作，将记录标志为异常，进入7天申诉期）
	FSRecordActionDelete		,		//删除（限超级管理员操作，直接从服务器删除数据）
};

typedef NS_ENUM(int, FSRecordSplitType)
{
	FSRecordSplitTypeDistance	,		//按距离分隔数据
	FSRecordSplitTypeTime		,		//按时间分隔数据
};

typedef struct {
	int         count, maxSumtime, maxDistance;
	
	FSRecordPointType	*type;
	int			*sumtime, *distance;
	
	//需要滤波的需声明为double
	double		*speed, *heart, *freq, *height, *power;
	double		*latitude, *longitude;
} FSRecordPoints;

#pragma mark - 记录点
/*===================================================================
 说明：
	运动记录点（记录点当前对应的数据，历史记录中部分属性有效）
 ==================================================================*/
@class FSGroup;
@interface FSRecordPoint : NSObject

@property (nonatomic, assign) FSRecordPointType	type;		//类型

@property (nonatomic, assign) CGFloat		speed;			//速度
@property (nonatomic, assign) CGFloat		height;			//海拔、坡度、阻力
@property (nonatomic, assign) int			freq;			//踏频、步频
@property (nonatomic, assign) int			heart;			//心率
@property (nonatomic, assign) CGFloat		power;			//功耗

@property (nonatomic, assign) double		distance;		//距离
@property (nonatomic, assign) CGFloat		calories;		//卡路里
@property (nonatomic, assign) int			count;			//计数
@property (nonatomic, assign) int			sumtime;		//总用时
@property (nonatomic, assign) double		latitude;		//纬度
@property (nonatomic, assign) double		longitude;		//经度
@property (nonatomic, assign) float			accuracy;		//精度

#pragma mark - 本地运动专用
@property (nonatomic, assign) int			runtime;		//运动用时
@property (nonatomic, assign) int			freetime;		//暂停用时

#pragma mark - 分隔专用
//下面属性仅在 FSRecord 中 pointForDistance、pointForDistances 使用
//速度（speed）(pointWithDistance是从上点开始算，pointWithDistances从起点开始算)
@property (nonatomic, assign) NSUInteger	index;			//对应数组中的索引
@property (nonatomic, assign) int			offset;			//与上点用时的差时(仅用于pointWithDistance)

@end

#pragma mark - 运动记录
/*===================================================================
 说明：
	运动秀记录
 备注：
	距离、速度、海拔已根据用户设置进行英制转换
 ==================================================================*/
@class FSUser, FSRecord, FSDevice, FSModel;

typedef void(^FSRecordResult) (FSRecord *record, NSError *error);

@interface FSRecord : NSObject

+ (void)synchroWithResult:(FSServerResult)result;				//同步完整记录（即将弃用），为保证效率使用不含数据的同步方式
+ (void)synchroWithoutDataResult:(FSServerResult)result;		//不含数据部分的同步记录方法

+ (id)recordWithRID:(uint)rid result:(FSRecordResult)result;	//获取指定ID的记录（优先获取本地的记录，获取后从result中返回）

- (instancetype)initWithParam:(NSDictionary *)param;			//从现有的数据中解析出记录（如：记录表获取到原始数据后传入）
- (instancetype)initWithParam:(NSDictionary *)param includeData:(BOOL)include;		//同上，可选择是否解析运动数据以提高运动效率

- (id)loadSportData:(FSRecordResult)result;						//为当前记录加载运动数据（优先获取本地的数据），若是本地则返回FSRecord对象

- (void)uploadWithResult:(FSRecordResult)result;				//上传记录到服务器，上传成功后有可能被服务器更改相关数据
- (void)deleteWithResult:(FSServerResult)result;				//删除记录（只能删除当前用户自己的记录）
- (id)actionWithAction:(FSRecordAction)action content:(NSString *)content result:(FSServerResult)result;		//记录操作（根据当前用户的权限可对非本人记录进行操作）

//
@property (nonatomic, readonly) FSRecordPoints	points;			//运动记录点原始数据组
@property (nonatomic, assign)	NSInteger		tag;

@property (nonatomic, readonly) BOOL			isMine;			//当前记录是否为登录用户的

#pragma mark - 记录属性
//运动信息属性
@property (nonatomic, readonly) uint			rid;			//记录ID
@property (nonatomic, readonly) NSDate			*datetime;		//运动开始时间
@property (nonatomic, readonly) FSSportType		type;			//运动记录类型
@property (nonatomic, assign)	FSRecordState	state;			//记录状态（在rid为0时，可修改）

@property (nonatomic, readonly) FSUser			*owner;			//记录所有者
@property (nonatomic, readonly) FSGroup			*group;			//记录所打卡圈子
@property (nonatomic, readonly) FSModel			*model;			//运动所用数据模型
@property (nonatomic, readonly) FSDevice		*device;		//运动所用设备

#pragma mark - 记录运动量
//运动量
@property (nonatomic, readonly) CGFloat			distance;		//运动距离（已根据用户设置进行英制转换）
@property (nonatomic, readonly) CGFloat			calories;		//运动卡路里
@property (nonatomic, readonly) int				sumtime;		//运动总时长（秒）
@property (nonatomic, readonly) int				runtime;		//运动时长
@property (nonatomic, readonly) int				freetime;		//暂停时长
@property (nonatomic, readonly) int				count;			//运动计数（如：步数，转数）

#pragma mark - 速度
@property (nonatomic, readonly) CGFloat			speed;			//平均速度
@property (nonatomic, readonly) CGFloat			maxSpeed;		//最快速度
@property (nonatomic, readonly) CGFloat			minSpeed;		//最慢速度

#pragma mark - 高度
@property (nonatomic, readonly) CGFloat			height;			//平均高度
@property (nonatomic, readonly) CGFloat			maxHeight;		//最高高度
@property (nonatomic, readonly) CGFloat			minHeight;		//最低高度

#pragma mark - 频率
@property (nonatomic, readonly) CGFloat			freq;			//平均频率
@property (nonatomic, readonly) CGFloat			maxFreq;		//最高频率
@property (nonatomic, readonly) CGFloat			minFreq;		//最低频率

#pragma mark - 心率
@property (nonatomic, readonly) CGFloat			heart;			//平均心率
@property (nonatomic, readonly) CGFloat			maxHeart;		//最高心率
@property (nonatomic, readonly) CGFloat			minHeart;		//最低心率

#pragma mark - 功耗
@property (nonatomic, readonly) CGFloat			power;			//平均功耗
@property (nonatomic, readonly) CGFloat			maxPower;		//最大功耗
@property (nonatomic, readonly) CGFloat			minPower;		//最小功耗

#pragma mark - 记录操作
- (instancetype)splitWithType:(FSRecordSplitType)type value:(CGFloat)value;		//生成按指定值分离后运动记录集（数据取平均值）
- (instancetype)splitWithType:(FSRecordSplitType)type value:(CGFloat)value keepStart:(BOOL)keep realSpeed:(BOOL)real;		//同上，同时指定是否保留起始点及是否计算真实段速度

//根据条件获取对应运动记录点
- (FSRecordPoint *)pointAtIndex:(NSUInteger)index;				//获取指定索引的记录点

- (NSArray <FSRecordPoint *> *)pointForDistances:(NSArray <NSNumber *> *)distances;
- (NSArray <FSRecordPoint *> *)pointForDistance:(CGFloat)distance includeEnd:(BOOL)end;

- (NSArray <FSRecordPoint *> *)pointForType:(FSRecordSplitType)type values:(NSArray <NSNumber *> *)values;
- (NSArray <FSRecordPoint *> *)pointForType:(FSRecordSplitType)type value:(CGFloat)value includeEnd:(BOOL)end;

- (void)calculate;							//解析后默认自动计算运动数值，若外部对数据进行滤波处理后，需要调用此方法重新计算新的运动数值
- (void)clipPointToRange:(NSRange)range;	//将数据点剪切到指定范围，并重新计算运动量（自动调用calculate）

#pragma mark - 记录打卡
- (NSArray <FSGroup *> *)supportGroups;		//获取支持当前记录打卡的圈子

@end

#pragma mark - 记录统计
@interface FSRecordTotal : NSObject

- (instancetype)initWithParam:(NSDictionary *)param;

@property (nonatomic, readonly) int				times;			//运动次数
@property (nonatomic, readonly) NSInteger		distance;		//运动距离
@property (nonatomic, readonly) NSInteger		runtime;		//运动用时
@property (nonatomic, readonly) NSInteger		calories;		//运动消耗
@property (nonatomic, readonly) NSInteger		count;			//运动计数

@end
